package com.netty.demo.server.utils;

import com.netty.demo.server.dll.CallLibrary;
import com.netty.demo.server.dll.CallLibrary.DemoCallbackImpl;
import com.netty.demo.server.dll.CallLibrary.DemoStructure;
import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.FloatByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;

import java.util.Arrays;

/**
 * jna调用dll文件工具类
 * Java和C的数据类型对照表
 * Java 类型                      C 类型                  原生表现
 * boolean                      int                     32位整数(可定制) 
 * byte                         char                    8位整数
 * char                         wchar_t                 平台依赖
 * short                        short                   16位整数
 * int                          int                     32位整数
 * long                         long, __int64           64位整数
 * float                        float                   32位浮点数
 * double                       double                  64位浮点数
 * Buffer/Pointer               pointer                 平台依赖(32或64位指针)
 * <T>[] (基本类型的数组)         pointer/array            32或64位指针(参数/返回值)邻接内存(结构体成员)
 * String                       char*                    /0结束的数组 (native encoding or jna.encoding)
 *  WString                      wchar_t*                /0结束的数组(unicode)
 *  Structure                    struct* /struct          指向结构体的指针(参数或返回值)
 * Union                        union                   等同于结构体
 * Structure[]                   struct[]                结构体的数组，邻接内存
 * Callback                     <T> (*fp)()             Java函数指针或原生函数指针
 * NativeMapped                 varies                  依赖于定义
 * NativeLong                   long                    平台依赖(32或64位整数)
 * PointerType                  pointer                 和Pointer相同
 *
 * @author Administrator 余秀良
 * @version 1.0
 * <p>date: 2019年09月10日  14:36 </p>
 * <p>address: 四川成都 </p>
 */
public final class JnaDllCallUtil {
    public static void main(String[] args) {


        CallLibrary.DemoStructure.ByReference byReference = new CallLibrary.DemoStructure.ByReference();
        byReference.a = 1;
        byReference.b = 3;

        IntByReference intByReference = new IntByReference();
        intByReference.setValue(1);
        intByReference.setPointer(new Pointer(1));


        CallLibrary.CALL_LIBRARY.method(byReference, intByReference);
        System.out.println(intByReference.getValue());

        System.out.println(CallLibrary.CALL_LIBRARY.method(byReference));

        CallLibrary.DemoStructure.ByValue byValue = new CallLibrary.DemoStructure.ByValue();
        byValue.a = 1;
        byValue.b = 3;

        int i = CallLibrary.CALL_LIBRARY.method(byValue);

        System.out.println(i);


        char[] chars1 = new char[123];
        chars1[0] = 0;
        chars1[1] = 2;
        CallLibrary.CALL_LIBRARY.method(1, 2, chars1);

        char[] chars = new char[123];

        FloatByReference floatByReference = new FloatByReference(0.1F);
        String result = CallLibrary.CALL_LIBRARY.method(floatByReference, chars);
        System.out.println(result);
        //指针对象
        DemoStructure.ByReference byReference1 = new DemoStructure.ByReference();
        //传值对象
        DemoStructure.ByValue byValue1 = new DemoStructure.ByValue();
        CallLibrary.CALL_LIBRARY.method(byReference1, byValue1);

        int helloWorld = CallLibrary.CALL_LIBRARY.method(new DemoCallbackImpl(), "Hello world", 1);
        System.out.println(helloWorld);
    }

    /**
     * 调用StdCall方式导出的DLL动态库方法
     * DLL文件默认路径为项目根目录
     * 若DLL文件存放在项目外，请使用绝对路径
     *
     * @author 余秀良
     * @version 1.0
     * <p>  date: 2019 - 09 - 12  10:40    </p>
     * <p>  address: 四川成都  </p>
     */
    public interface CallStdCallLibrary extends StdCallLibrary {
        //dll文件路径加文件名   不需要写  .dll
        CallStdCallLibrary CALL_STD_CALL_LIBRARY = Native.load("C:\\Windows\\System32\\msvcrt", CallStdCallLibrary.class);
    }

    public static class CallBack {
        public static void main(String[] args) {
            CLibrary cLibrary = Native.load("C:\\Windows\\System32\\msvcrt", CLibrary.class);
            CLibrary.NotificationListenerImpl callbackImpl = new CLibrary.NotificationListenerImpl();
            cLibrary.callback(callbackImpl);
        }

        public interface CLibrary extends Library {
            void callback(NotificationListener callback);

            interface NotificationListener extends Callback {
                void invoke(Pointer val, int length);
            }

            class NotificationListenerImpl implements NotificationListener {
                @Override
                public void invoke(Pointer val, int length) {
                    System.out.println(length);
                    System.out.println(Arrays.toString(val.getByteArray(0, length)));
                }
            }
        }
    }
}
